package com.huanzhidadi.springsecurity.controller;

import com.alibaba.fastjson2.JSON;
import com.huanzhidadi.springsecurity.feign.FeignService;
import com.huanzhidadi.springsecurity.model.BaseResultVO;
import com.huanzhidadi.springsecurity.model.ItemVO;
import com.huanzhidadi.springsecurity.service.TestService;
import com.huanzhidadi.springsecurity.util.ServletUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;

@Slf4j
@RestController
public class TestController {

    @Autowired
    private FeignService feignService;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private TestService testService;

    @PreAuthorize("hasAuthority('system:hello:view')")
    @GetMapping("/hello")
    public String hello() {
        return "hello spring security";
    }

    /**
     * 在SPEL表达式中使用@xx相当于获取容器中bean的名称为xx的对象
     * @return
     */
    @PreAuthorize("@mySecurityEx.hasPreAuthority('system:test:view')")
    @GetMapping("/helloTest")
    public String helloTest() {
        return "helloTest";
    }


    @PreAuthorize("@mySecurityEx.hasPreAuthority('system:test:feign')")
    @RequestMapping(value = "client1", method = RequestMethod.POST)
    public BaseResultVO client1(@RequestBody ItemVO itemVO) {
        log.info("client1");
        BaseResultVO baseResultVO = feignService.requestBody(itemVO);
        log.info(JSON.toJSONString(baseResultVO));
        return baseResultVO;
    }

    @PreAuthorize("@mySecurityEx.hasPreAuthority('system:test:feign')")
    @RequestMapping(value = "client1Delay", method = RequestMethod.POST)
    public BaseResultVO client1Delay(@RequestBody ItemVO itemVO) {
        log.info("client1Delay");
        BaseResultVO baseResultVO = feignService.requestDelay(itemVO);
        log.info(JSON.toJSONString(baseResultVO));
        return baseResultVO;
    }

    /**
     * 显式传递token参数
     * @param itemVO
     * @return
     */
    @PreAuthorize("@mySecurityEx.hasPreAuthority('system:test:feign')")
    @RequestMapping(value = "transUserToken", method = RequestMethod.POST)
    public BaseResultVO transUserToken(@RequestBody ItemVO itemVO) {
        log.info("transUserToken");
        String token = ServletUtils.getRequest().getHeader("token");
        BaseResultVO baseResultVO = feignService.transUserToken(itemVO, token);
        log.info(JSON.toJSONString(baseResultVO));
        return baseResultVO;
    }

    /**
     * 隐式传递token参数
     * @param itemVO
     * @return
     */
    @PreAuthorize("@mySecurityEx.hasPreAuthority('system:test:feign')")
    @RequestMapping(value = "transUserWithoutToken", method = RequestMethod.POST)
    public BaseResultVO transUserWithoutToken(@RequestBody ItemVO itemVO) {
        log.info("transUserToken");
        BaseResultVO baseResultVO = feignService.transUserWithoutToken(itemVO);
        log.info(JSON.toJSONString(baseResultVO));
        return baseResultVO;
    }

    /**
     * 异步调用Feign接口
     * @param itemVO
     * @return
     */
    @PreAuthorize("@mySecurityEx.hasPreAuthority('system:test:feign')")
    @RequestMapping(value = "transUserWithThread", method = RequestMethod.POST)
    public BaseResultVO transUserWithThread(@RequestBody ItemVO itemVO) {
        log.info("transUserWithThread");
        // 子线程共享主线程的request对象
        RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(), true);
        threadPoolTaskExecutor.execute(() -> feignService.transUserWithoutToken(itemVO));
        return BaseResultVO.success();
    }

    /**
     * GET请求调用Feign接口
     * @return
     */
    @PreAuthorize("@mySecurityEx.hasPreAuthority('system:test:feign')")
    @RequestMapping(value = "transUserWithGetReq", method = RequestMethod.GET)
    public BaseResultVO transUserWithGetReq() {
        log.info("transUserWithGetReq");
        return feignService.transUserWithGetReq();
    }

    /**
     * 同模块同步调用
     * @return
     */
    @PreAuthorize("@mySecurityEx.hasPreAuthority('system:test:aaa')")
    @RequestMapping(value = "transUserSync", method = RequestMethod.POST)
    public BaseResultVO transUserSync() {
        log.info("transUserSync");
        return testService.transUserSync();
    }

    /**
     * 同模块异步调用
     * @return
     */
    @PreAuthorize("@mySecurityEx.hasPreAuthority('system:test:aaa')")
    @RequestMapping(value = "transUserAsync", method = RequestMethod.POST)
    public BaseResultVO transUserAsync() {
        log.info("transUserAsync");
        threadPoolTaskExecutor.execute(() -> testService.transUserAsync());
        return BaseResultVO.success();
    }

}
